﻿namespace ClassyBlog.Web.Specs.Unit
{
    using System;
    using System.Web.Mvc;

    using Machine.Specifications;
    using NSubstitute;

    using ExtensionMethods;
    using Infrastructure;

    [Subject(typeof(ContentProxyController))]
    public class when_creating_content_proxy_controller_with_null_http
    {
        static Exception exception;

        Because of = () => exception =
            Catch.Exception(() => new ContentProxyController(null));

        It should_throw_exception = () =>
            exception.ShouldBeOfType<ArgumentNullException>();
    }

    public abstract class ContentProxyControllerSpec
    {
        protected static IHttp http;
        protected static ContentProxyController controller;

        Establish context = () =>
        {
            http = Substitute.For<IHttp>();
            controller = new ContentProxyController(http);
        };
    }

    [Subject(typeof(ContentProxyController))]
    public class when_starting_to_get_content : ContentProxyControllerSpec
    {
        private static int asyncCount;

        Establish context = () =>
            asyncCount = controller.AsyncManager.OutstandingOperations.Count;

        Because of = () => controller.GetAsync("http://kazimanzurrashid.com");

        It should_incement_async_operation_count = () =>
            (controller.AsyncManager.OutstandingOperations.Count >
            asyncCount).ShouldBeTrue();

        It should_use_http_service = () =>
            http.Received()
                .GetAsync(
                Arg.Any<Uri>(), Arg.Any<Action<bool, int, string, string>>());
    }

    [Subject(typeof(ContentProxyController))]
    public class when_completing_to_get_content : ContentProxyControllerSpec
    {
        Establish context = () =>
            http.When(x => x.GetAsync(
                Arg.Any<Uri>(),
                Arg.Any<Action<bool, int, string, string>>())).
                Do(info =>
        {
            var callback = (Action<bool, int, string, string>)info.Args()[1];

            callback(false, 200, "text/html", "<h1>Hello world</h1>");
        });

        Because of = () => controller.GetAsync("http://kazimanzurrashid.com");

        It should_set_whether_operation_ended_up_in_error = () =>
            controller.AsyncManager
                      .Parameters["error"]
                      .To<bool>()
                      .ShouldBeFalse();

        It should_set_http_status_code = () => controller.AsyncManager.Parameters["statusCode"].ShouldEqual(200);

        It should_set_content_type = () => controller.AsyncManager.Parameters["type"].ShouldEqual("text/html");

        It should_set_content = () => controller.AsyncManager.Parameters["content"].ShouldEqual("<h1>Hello world</h1>");
    }

    [Subject(typeof(ContentProxyController))]
    public class when_content_is_successfully_received :
        ContentProxyControllerSpec
    {
        static ActionResult result;

        Because of = () =>
            result = controller.GetCompleted(
            false, 200, "text/html", "<h1>Hello world</h1>");

        It should_return_http_status_code_result = () =>
            result.ShouldBeOfType<ContentResult>();
    }

    [Subject(typeof(ContentProxyController))]
    public class when_error_occurs_while_getting_content :
        ContentProxyControllerSpec
    {
        static ActionResult result;

        Because of = () =>
            result = controller.GetCompleted(true, 500, null, null);

        It should_return_http_status_code_result = () =>
            result.ShouldBeOfType<HttpStatusCodeResult>();
    }
}